package cn.ktouch.devtools;

import android.util.Log;
import android.app.Activity;
import android.widget.Button;
import android.widget.TextView;
import android.widget.EditText;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import cn.ktouch.internallib.ReadWriteFlagQrd;
import android.view.View;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import cn.ktouch.devtools.R;
import android.util.KTFeature;
import android.text.TextUtils;
import android.widget.Switch;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.view.View.OnTouchListener;
import java.util.ArrayList;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.view.MotionEvent;
import android.content.Context;
import java.util.List;
import cn.ktouch.internallib.MMIJni;

public class LockFrequency extends Activity implements Button.OnClickListener{
	private static final String TAG = "KtDevTools.LockFrequency";
	private Button lockset7M = null;
	private Button lockset18M = null;
	private Button restoreset = null;
	private Button lockBand = null;
	private Button unlockBand = null;
	private Button lockByNVValue = null;
	private TextView lteNote = null;
	private TextView currentValue = null;
	private boolean isLTE700M_Locked = false;
	private boolean isLTE1800M_Locked = false;

	private EditText editTextBandValue = null;
	private EditText editTextNVValue = null;

	private final int LTE700M_MOVESIZE = 28;
	private final int LTE1800M_MOVESIZE = 3;
	private long oldFrequency = 0;
	private long valueInFile = 0;
	private long RESTORE_NV_VALUE = 0;
	private boolean lockFDiv = false;

	// final long current NV = 524357;
	private Button selectAllBand = null;
	private Button differentBand = null;
	private Button registerBand = null;
	private Button frequencyCN = null;
	private Switch switchLte = null;
	long currentNV = 0;
	long selectNV = 0;
	long differentNV = 0;
	long lteBandpref = 0;
	private ListView areaCheckListView;
	ArrayList<BandListItem> bandItems;
	ArrayList<BandListItem> differentItems;

	private enum LockMethod{
		BYTE_ADDR,
		INT_ADDR,
		STRING_ADDR
	}

	private LockMethod mLockMethod = LockMethod.INT_ADDR;

	private TextView cellInfo = null;
	private final int UPDATE_INFO = 1;
	private final int DELAY_TIME = 1000;
	private Handler mHandler = new Handler() {
		public void handleMessage(Message msg) {
			if (msg.what == UPDATE_INFO) {
				Log.i(TAG, "-->> update info");
				updateCellInfo();
			}
		}
	};

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.lock_frequency);
		lockFDiv = "true".equals(KTFeature.get("LOCK_F_DIV"));
		String value = android.util.KTFeature.get("NV_LOCK_VALUE");
		if(!TextUtils.isEmpty(value) && value.matches("[0-9]+")){
			RESTORE_NV_VALUE = Long.valueOf(value);
		}
	}

	public void onResume() {
		super.onResume();
		init();
	}

	private void init(){
		lteNote = (TextView)findViewById(R.id.ltenote);
		currentValue = (TextView)findViewById(R.id.currentValue);
		lockset7M = (Button)findViewById(R.id.lockset7M);
		lockset7M.setOnClickListener(this);
		lockset18M = (Button)findViewById(R.id.lockset18M);
		lockset18M.setOnClickListener(this);

		restoreset = (Button)findViewById(R.id.restoreset);
		restoreset.setOnClickListener(this);

		lockBand = (Button)findViewById(R.id.lock_band);
		lockBand.setOnClickListener(this);
		lockBand.setText(R.string.lockBand);

		unlockBand = (Button)findViewById(R.id.unlock_band);
		unlockBand.setOnClickListener(this);
		unlockBand.setText(R.string.unlockBand);

		lockByNVValue = (Button)findViewById(R.id.lockByNVValue);
		lockByNVValue.setOnClickListener(this);

		editTextBandValue= (EditText)findViewById(R.id.bandValue);
		editTextNVValue = (EditText)findViewById(R.id.nvValue);

		selectAllBand = (Button)findViewById(R.id.selectAllBand);
		selectAllBand.setOnClickListener(this);
		switchLte = (Switch)findViewById(R.id.switchAllBand);
		differentBand = (Button)findViewById(R.id.differentBand);
		differentBand.setOnClickListener(this);
		registerBand = (Button)findViewById(R.id.registerBand);
		registerBand.setOnClickListener(this);
		frequencyCN = (Button)findViewById(R.id.frequencyCN);
		frequencyCN.setOnClickListener(this);

		isLTE700M_Locked = isLockState(LTE700M_MOVESIZE);
		isLTE1800M_Locked = isLockState(LTE1800M_MOVESIZE);

		oldFrequency = readAllBand();
		/*
		int ret = readFrequencyValue();
		if(ret>0){
			Log.i(TAG, "-->> no need write in file  = " + oldFrequency);
		}else{
			writeFrequencyValue(oldFrequency);
			Log.i(TAG, "-->>need write in file = " + ret);
		}
		*/

		lteBandpref = readtemp();
		//differentNV = Math.abs(oldFrequency-lteBandpref);;
		//differentNV = ~((~oldFrequency)&(~lteBandpref));
		differentNV = oldFrequency^lteBandpref;
		Log.i(TAG, "-->> 65633NV item  = " + lteBandpref + ", oldFrequency = " + oldFrequency +
                ", differentNV = " + differentNV );

		long dValue = oldFrequency - (1<<LTE700M_MOVESIZE) - (1<<LTE1800M_MOVESIZE);
		if(isLTE700M_Locked && isLTE1800M_Locked && (dValue==0)){
			lteNote.setText(R.string.lock_LTE_success);
		}else{
			lteNote.setText(R.string.unlock_LTE_success);
		}

//
		currentNV = oldFrequency;
		showCurrentNVValue(currentNV);
		bandItems = getBandData(currentNV);

		switchLte = (Switch) findViewById(R.id.switchAllBand);
		if (currentNV > 0) {
			switchLte.setChecked(true);
		}

		switchLte.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {

				if (MotionEvent.ACTION_UP == event.getAction()) {
					Log.i(TAG, "switch ontouch up");
					if (switchLte.isChecked()) {
						Log.i(TAG, "clear band");
						switchLte.setChecked(false);
						clearBandData(bandItems);
						cleanAllBand();
						showCurrentNVValue(readAllBand());
					} else {
						bandItems = getBandData(RESTORE_NV_VALUE);
						createDialog("Select band", getBandNames(bandItems), getBandState(bandItems), RESTORE_NV_VALUE);
					}
					return true;
				} else {
					return true;
				}
			}
		});

		switchLte.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			@Override
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				if (isChecked) {
					Log.i(TAG, "switch checked = " + isChecked + ", modify band");
				} else {
					Log.i(TAG, "switch checked = " + isChecked + ", clear all band");
					currentNV = 0;
				}
			}
		});
		cellInfo = (TextView)findViewById(R.id.cell_info);
		updateCellInfo();
	}

	public void updateCellInfo() {
		cellInfo.setText(getCellInfo());
		mHandler.sendEmptyMessageDelayed(UPDATE_INFO, DELAY_TIME);
	}

	public void onClick(View v) {
		int moveSize = -1;
		String value = "";
		if(v == lockset7M){
			lockUnlockBand(String.valueOf(LTE700M_MOVESIZE), true);
		}else if(v == lockset18M){
			lockUnlockBand(String.valueOf(LTE1800M_MOVESIZE), true);
		}else if(v == restoreset){
			currentNV = RESTORE_NV_VALUE;
			writeBandByNV(RESTORE_NV_VALUE);
		}else if(v == lockBand){
			value = editTextBandValue.getText().toString();
			lockUnlockBand(value, true);
		}else if(v == unlockBand){
			value = editTextBandValue.getText().toString();
			lockUnlockBand(value, false);
		}else if(v == lockByNVValue){
			value = editTextNVValue.getText().toString();
			lockByWriteNVValue(value);
		}else if(v == selectAllBand){
			//bandItems = getBandData(RESTORE_NV_VALUE);
			//createDialog(getBandNames(bandItems), getBandState(bandItems), RESTORE_NV_VALUE);
			bandItems = getBandData(currentNV);
			createDialog("Select band", getBandNames(bandItems), getBandState(bandItems), currentNV);
		}else if(v == differentBand){
			//differentNV = Math.abs(currentNV-lteBandpref);
			differentNV = currentNV^lteBandpref;
			differentItems = getDiffBandData(differentNV);
			createDiffDialog("Different band", getBandNames(differentItems),
					getBandState(differentItems), differentNV);
		}else if(v == registerBand){
			differentItems = getDiffBandData(1111);
			createRegisterDialog("Registered band", getBandNames(differentItems),
					getBandState(differentItems), differentNV);
		}else if(v == frequencyCN){
			String [] item = {getCellInfo()};
			createFreqCNDialog("Cell Info", item);
		}
		showCurrentNVValue(readAllBand());
	}

	private boolean isHexNember(String nvValue){
		String validate = "(?i)[0-9a-f]+";
		return nvValue.matches(validate);
	}
	private void lockByWriteNVValue(String nvValue){
		if(isHexNember(nvValue)){
			Long valueLong = Long.valueOf(nvValue, 16);
			long value = valueLong.longValue();
			boolean result = false;
			if (lockFDiv) {
				result = ReadWriteFlagQrd.restoreBand(value, ReadWriteFlagQrd.NV_TY_MMI_LOCK_F_I) &&
						ReadWriteFlagQrd.restoreBand(value, ReadWriteFlagQrd.NV_TY_MMI_LOCK_F_DIV_I);
			}else{
				result = ReadWriteFlagQrd.restoreBand(value, ReadWriteFlagQrd.NV_TY_MMI_LOCK_F_I) &&
						ReadWriteFlagQrd.restoreBand(value, ReadWriteFlagQrd.SYS_SELECTION_LTE_BAND_PREF);
			}
			if(result){
				Toast.makeText(this, getString(R.string.lock_LTE_success), Toast.LENGTH_SHORT).show();
				currentNV = value;
				Log.i(TAG, "-->> currentNV" + currentNV);
			}else{
				Toast.makeText(this, getString(R.string.lock_LTE_fail), Toast.LENGTH_SHORT).show();
			}
		}else{
			Toast.makeText(this, getString(R.string.invalidnvValueNote), Toast.LENGTH_SHORT).show();
		}
	}

	private boolean isLockState(int moveSize){
		if (lockFDiv) {
			return ReadWriteFlagQrd.readLockFreqencyState(moveSize, ReadWriteFlagQrd.NV_TY_MMI_LOCK_F_I)&&
				   ReadWriteFlagQrd.readLockFreqencyState(moveSize, ReadWriteFlagQrd.NV_TY_MMI_LOCK_F_DIV_I);
		}else{
			return ReadWriteFlagQrd.readLockFreqencyState(moveSize, ReadWriteFlagQrd.NV_TY_MMI_LOCK_F_I) &&
				   ReadWriteFlagQrd.readLockFreqencyState(moveSize, ReadWriteFlagQrd.SYS_SELECTION_LTE_BAND_PREF);
		}
	}

	private void cleanAllBand(){
		ReadWriteFlagQrd.restoreBand(0, ReadWriteFlagQrd.NV_TY_MMI_LOCK_F_I);
		if (lockFDiv) {
			ReadWriteFlagQrd.restoreBand(0, ReadWriteFlagQrd.NV_TY_MMI_LOCK_F_DIV_I);
		} else {
			ReadWriteFlagQrd.restoreBand(0, ReadWriteFlagQrd.SYS_SELECTION_LTE_BAND_PREF);
		}
	}

	private void writeBandByNV(long nv){
		boolean result = false;
		if (lockFDiv) {
			result = ReadWriteFlagQrd.restoreBand(nv, ReadWriteFlagQrd.NV_TY_MMI_LOCK_F_I)&&
					 ReadWriteFlagQrd.restoreBand(nv, ReadWriteFlagQrd.NV_TY_MMI_LOCK_F_DIV_I);
		} else {
			result = ReadWriteFlagQrd.restoreBand(nv, ReadWriteFlagQrd.NV_TY_MMI_LOCK_F_I) &&
					 ReadWriteFlagQrd.restoreBand(nv, ReadWriteFlagQrd.SYS_SELECTION_LTE_BAND_PREF);
		}

		long readAll = readAllBand();
		if(nv==readAll){
			Toast.makeText(this, getString(R.string.write_nv_success), Toast.LENGTH_SHORT).show();
		}else{
			Toast.makeText(this, getString(R.string.write_nv_fail), Toast.LENGTH_SHORT).show();
		}
	}

	private long readtemp(){
			return  524359;
			//return ReadWriteFlagQrd.readFromModemLong(65633);
	}

	private long readAllBand(){
		if (lockFDiv) {
			return ReadWriteFlagQrd.readFromModemLong(ReadWriteFlagQrd.NV_TY_MMI_LOCK_F_I)&
					ReadWriteFlagQrd.readFromModemLong(ReadWriteFlagQrd.NV_TY_MMI_LOCK_F_DIV_I);
		}else{
			return ReadWriteFlagQrd.readFromModemLong(ReadWriteFlagQrd.NV_TY_MMI_LOCK_F_I)&
					ReadWriteFlagQrd.getSysSelectionPref(ReadWriteFlagQrd.SYS_SELECTION_LTE_BAND_PREF);
		}
	}
	private void showCurrentNVValue(long nv){
		if (lteBandpref==nv) {
			differentBand.setVisibility(View.GONE);
		} else {
			differentBand.setVisibility(View.VISIBLE);
		}
		differentBand.setVisibility(View.GONE);
		registerBand.setVisibility(View.GONE);
		currentValue.setText(getString(R.string.currentNVValue) + "0x" + Long.toHexString(nv));
	}

	private void lockUnlockBand(String value, boolean lock){
		if(value.isEmpty()){
			Toast.makeText(this, getString(R.string.band_empty), Toast.LENGTH_SHORT).show();
		}else{
			if(lock){
				cleanAllBand();
			}
			int moveSize = Integer.parseInt(value);
			if(moveSize>=1&&moveSize<=64){
				ReadWriteFlagQrd.lockOrUnlockFrequency(moveSize-1, lock, ReadWriteFlagQrd.NV_TY_MMI_LOCK_F_I);
				if (lockFDiv) {
					ReadWriteFlagQrd.lockOrUnlockFrequency(moveSize-1, lock, ReadWriteFlagQrd.NV_TY_MMI_LOCK_F_DIV_I);
				} else {
					ReadWriteFlagQrd.lockOrUnlockFrequency(moveSize-1, lock, ReadWriteFlagQrd.SYS_SELECTION_LTE_BAND_PREF);
				}
				boolean isLocked = isLockState(moveSize-1);
				if(isLocked){
					Toast.makeText(this, getString(R.string.band) + moveSize + getString(R.string.locked), Toast.LENGTH_SHORT).show();
				}else{
					Toast.makeText(this, getString(R.string.band) + moveSize + getString(R.string.unlocked), Toast.LENGTH_SHORT).show();
				}
			}else{
				Toast.makeText(this, "please input valid band number ", Toast.LENGTH_SHORT).show();
			}
		}
	}

	private void writeFrequencyValue(long value){
		byte buf[] = Long.toString(value).getBytes();
		FileOutputStream out = null;
		try{
			File file = new File("/data/qrdNVValue.txt");
			if(!file.exists()){
				file.createNewFile();
			}
			out = new FileOutputStream(file);//write(byte[] buffer, int byteOffset, int byteCount)
			out.write(buf, 0, buf.length);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(out != null){
				try{
					out.close();
				}catch(Exception e){
					e.printStackTrace();
				}
			}
		}
	}

	private int readFrequencyValue(){
		byte buf[] = new byte[12];
		int ret = 0;
		FileInputStream in = null;
		try{
			File file = new File("/data/qrdNVValue.txt");
			if(file.exists()){
				in = new FileInputStream(file);
				BufferedInputStream buff=new BufferedInputStream(in);
				ret = buff.read(buf, 0, 12);
				if(ret>0){
					valueInFile = Long.parseLong(new String(buf, 0, ret));
				}
				Log.i(TAG, "-->> read from file ret = " + ret + ", valueInFile = " + valueInFile);
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(in != null){
				try{
					in.close();
				}catch(Exception e){
					e.printStackTrace();
				}
			}
		}
		return ret;
	}

//
	public ArrayList<BandListItem> getBandData(long nv) {
		ArrayList<BandListItem> mItems = new ArrayList<BandListItem>();
		for (int i = 0; i < 64; i++) {
			long b = 1;
			boolean checked = (nv & (b << i)) == (b << i);
			Log.i(TAG, " checked = " + checked + ", i = " + i + ", bnum" + (b << i));
			mItems.add(new BandListItem(i, "band " + String.valueOf(i + 1), checked));
		}
		return mItems;
	}

	public void clearBandData(ArrayList<BandListItem> mItems) {
		int size = mItems.size();
		for (int i = 0; i < size; i++) {
			mItems.set(i, new BandListItem(i, "band " + String.valueOf(i + 1), false));
		}
	}

	public String[] getBandNames(ArrayList<BandListItem> mItems) {
		int size = mItems.size();
		String[] names = new String[size];
		for (int i = 0; i < size; i++) {
			names[i] = mItems.get(i).bandname;
		}
		return names;
	}

	public boolean[] getBandState(ArrayList<BandListItem> mItems) {
		int size = mItems.size();
		boolean[] checks = new boolean[size];
		for (int i = 0; i < size; i++) {
			checks[i] = mItems.get(i).checked;
		}
		return checks;
	}

	public ArrayList<BandListItem> getDiffBandData(long nv) {
		ArrayList<BandListItem> mItems = new ArrayList<BandListItem>();
		for (int i = 0; i < 64; i++) {
			long b = 1;
			boolean checked = (nv & (b << i)) == (b << i);
			if (checked) {
				Log.i(TAG, " checked = " + checked + ", i = " + i + ", bnum" + (b << i));
				mItems.add(new BandListItem(i, "band " + String.valueOf(i + 1), checked));
			}
		}
		return mItems;
	}

	/*
	 * param nvp, nvp is 0, when only locked select band , nvp is other , when
	 * locked select band and default band
	 */
	private void createDialog(String title, String[] bandName, boolean[] bandState, long nvp) {
		selectNV = nvp;
		AlertDialog ad = new AlertDialog.Builder(LockFrequency.this).setTitle(title)
				.setMultiChoiceItems(bandName, bandState, new DialogInterface.OnMultiChoiceClickListener() {
					public void onClick(DialogInterface dialog, int whichButton, boolean isChecked) {
						long valueTrue = 1;
						int bandnum = Integer.valueOf(bandItems.get(whichButton).bandnum).intValue();
						if (isChecked) {
							selectNV |= valueTrue << bandnum;
						} else {
							selectNV &= ~(valueTrue << bandnum);
						}
						bandItems.set(whichButton, new BandListItem(bandnum, "band" + String.valueOf(bandnum + 1),
								isChecked));
						Log.d(TAG, "whichButton = " + whichButton + ", bandnum = " + bandnum + ", isChecked = "
								+ isChecked + ", selectNV = " + selectNV);
					}
				}).setPositiveButton(getString(android.R.string.ok), new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {
						String s = "value";
						// button.setText("value: " + value);
						currentNV = selectNV;
						if (currentNV > 0) {
							switchLte.setChecked(true);
						} else {
							switchLte.setChecked(false);
						}
						writeBandByNV(currentNV);
						showCurrentNVValue(readAllBand());
						Log.i(TAG, "select size = " + areaCheckListView.getCheckedItemPositions().size()
								+ ", modify band currentNV = " + currentNV + ", currentNV(0x): "
								+ Long.toHexString(currentNV));
						dialog.dismiss();
					}
				}).setNegativeButton(getString(android.R.string.cancel), null).create();
		areaCheckListView = ad.getListView();
		ad.show();
	}

	private void createDiffDialog(String title, String[] bandName, boolean[] bandState, long nvp) {
		selectNV = nvp;
		AlertDialog ad = new AlertDialog.Builder(LockFrequency.this).setTitle(title)
				.setMultiChoiceItems(bandName, bandState, new DialogInterface.OnMultiChoiceClickListener() {
					public void onClick(DialogInterface dialog, int whichButton, boolean isChecked) {
					}
				}).setNegativeButton(getString(android.R.string.cancel), null).create();
		areaCheckListView = ad.getListView();
		ad.show();
	}

	private void createRegisterDialog(String title, String[] bandName, boolean[] bandState, long nvp) {
		selectNV = nvp;
		AlertDialog ad = new AlertDialog.Builder(LockFrequency.this).setTitle(title)
				.setItems(bandName, new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {
					}
				}).setNegativeButton(getString(android.R.string.cancel), null).create();
		areaCheckListView = ad.getListView();
		ad.show();
	}

	private void createFreqCNDialog(String title, String[] freqpoint) {
		AlertDialog ad = new AlertDialog.Builder(LockFrequency.this).setTitle(title)
				.setItems(freqpoint, new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {
					}
				}).setNegativeButton(getString(android.R.string.cancel), null).create();
		areaCheckListView = ad.getListView();
		ad.show();
	}

	String[] cellType = {"Unknown", "GSM", "CDMA", "LTE", "WCDMA", "TD_SCDMA"};

	private String getCellInfo() {
		String strCellInfo = "Type: none, ID: none, EARFCN: none";
		int[] cellInfo = MMIJni.getRegisteredCellInfo_Interface();
		if (cellInfo!=null && cellInfo.length==3) {
			if (cellInfo[0]>0 && cellInfo[0]< cellType.length) {
				strCellInfo ="Type: " + cellType[cellInfo[0]] + ", ID: " + cellInfo[1] + ", EARFCN: " + cellInfo[2];
			} else {
				strCellInfo ="Type: " + cellType[0] + ", ID: " + cellInfo[1] + ", EARFCN: " + cellInfo[2];
			}
		}
		return strCellInfo;
	}
	//

}

	class BandListItem {
	public  int bandnum;
	public  String bandname;
	public  boolean checked;
	public BandListItem(int bandnum, String title, boolean checked) {
		this.bandnum = bandnum;
		this.bandname = title;
		this.checked = checked;
	}
}

